home *** CD-ROM | disk | FTP | other *** search
- Target: CrackMe [id:13]
- Author: tC...
- Cracker: The AntiXryst [CrossOver]
- Rating: Easy. I know tC... having written worse things.
- Used tools: WDASM 8.93, Hex Workshop
- Greetings to: Me, myself and I and everybody else I injured during my
- sadomasochistic games ;-)
-
-
- Hi there!
-
- You have probably read my tutorial on getting past tC's CrackMe id:12.
- If you did not and now do not know how to find relevant procedures of
- Delphi-written programs, read it NOW!
-
- As you may already have experienced, I will NOT explain every single
- detail, I'll just show you what part of code does what in a syntactical
- mix of Pascal and ASM register calling...
- If you browse through the disassembly and get closer to its sense,
- you'll soon recognise that the Delphi compiler is VERY stupid and
- produces completely inefficient, sometimes even idiotic code.
-
- And now launch WDASM, disassemble the crackme and set a breakpoint to
- $00441908, what is actually "our" routine. Feel free either just to
- read my text or to follow my steps with the debugger...
-
-
- Code snippet $00441924-$004419B0:
- ---------------------------------
- String data from the input boxes is read through the Delphi VCL and
- stored in pre-defined memory offsets. You'll find a string reference to
- "Yeah, You did it!" followed by a call - do not worry, this is just a
- hoax, because the called routine $00403850 has no relevance for the
- generation of serial numbers/key values due to its position in the VCL
- fully linked to the executable and because the value returned by this
- function in EAX is ignored by XOR EAX,EAX ($00441931).
-
-
-
- Code snippet $004419B5-$004419C8:
- ---------------------------------
- A relevant function is called - $004418D0. It seems to test something.
- This routine stores its result in [$00443838]. If this result is 2, the
- program continues. Elseway it calls a "clean-up" routine at $004417E4
- which deletes some calculated values and memory-stored string data from
- the input boxes, after the call returns, the jump to $00441AF5 is
- performed thus "our" relevant routine is terminated.
-
-
-
- Subroutines $004418D0 and $004418AC:
- ------------------------------------
- The routine $004418D0 does perform a check whether memory-stored string
- values from the upper 2 input boxes are longer than 0. You could also
- say that this function checks whether the values have been entered at
- all. If both values are present, routine $004418AC is called.
- The routine $004418AC performs via subtraction a compare of string
- lengths. If they are same, $00443838 becomes 2.
-
-
-
- Code snippet $004419DC-$00441A17:
- ---------------------------------
- In this code snippet the entered serial number is validated without a
- correct serial number is being generated.
-
- :004419DC lea edx, dword ptr [ebp-08] <---- getting User entry
- :004419DF mov eax, dword ptr [esi+000002C4] from input box
- :004419E5 call 004231A4 via VCL call
-
- :004419EA mov eax, dword ptr [ebp-08] <---- offset of User
- :004419ED movzx eax, byte ptr [eax+ebx-01] <---- ASCII value is loaded,
- :004419F2 add eax, 00000003 increased by 3
- :004419F5 push eax <---- and stored
-
- :004419F6 lea edx, dword ptr [ebp-0C] <---- getting Serial entry
- :004419F9 mov eax, dword ptr [esi+000002C8] from input box
- :004419FF call 004231A4 via VCL call
-
- :00441A04 mov eax, dword ptr [ebp-0C] <---- offset of Serial
- :00441A07 movzx eax, byte ptr [eax+ebx-01] <---- getting ASCII value
- :00441A0C pop edx <---- loading User char+3
- :00441A0D sub edx, eax
- :00441A0F add dword ptr [00443840], edx <---- difference between
- User char+3 and Serial
- char
-
- :00441A15 inc ebx <---- EBX is index counter
- :00441A16 dec edi <---- EDI is loop counter
- :00441A17 jne 004419DC
-
- You can sum up this in a sort of Pascal syntax:
- var index:Cardinal;
- for index:=1 to Length(User) do
- [00443840]:=[00443840]+(Ord(Name[index])+3-Ord(Serial[index]));
-
-
-
- Code snippet $00441A19-$00441A25:
- ---------------------------------
- A call to the routine $0044182C is performed. This routine is a hoax,
- intended to confuse the cracker. Why? Surely it does some string mani-
- pulation with XOR, addition and subtraction. But it does not store any
- calculated values ;-) After the call, offset $00443840 is checked
- whether it's 0. If not, the routine terminates. Do you see that the
- manipulated string and the serial must match? So here's the algorithm:
- var index:Cardinal;
- Serial:='';
- for index:=1 to Length(User) do
- Serial:=Serial+Chr(Ord(User[index])+3);
-
-
-
- Code snippet $00441A31-$00441A3D:
- ---------------------------------
- The string value for RegCode is obtained through the VCL and checked,
- whether it has been entered (length > 0). If the string is not present,
- the routine terminates.
-
-
-
- Code snippet $00441A49-$00441A7D:
- ---------------------------------
- A call to the hoax routine $004418AC is performed. The length of Serial
- and RegCode are checked, they must be the same, elseway the routine
- terminates.
-
- :00441A5E mov eax, dword ptr [00443848] <---- offset of RegCode
- :00441A63 call 00403A34 <---- call to Length()
- :00441A68 mov ebx, eax <---- result stored
- :00441A6A mov eax, dword ptr [0044384C] <---- offset to Serial
- :00441A6F call 00403A34 <---- call to Length()
- :00441A74 cmp ebx, eax <---- compare the lengths
- :00441A76 je 00441A7F <---- if OK, then continue
-
-
-
- Code snippet $00441A89-$00441A:
- ---------------------------------
- In this code snippet the entered RegCode is validated without a valid
- RegCode is being generated. This is the same as the validation of the
- Serial string, there's just one difference - instead of increasing by 3
- the chars of the user name are decreased by 3.
-
- :00441A8E lea edx, dword ptr [ebp-08] <---- getting User entry
- :00441A91 mov eax, dword ptr [esi+000002C4]
- :00441A97 call 004231A4
-
- :00441A9C mov eax, dword ptr [ebp-08] <---- now decreasing its
- :00441A9F movzx eax, byte ptr [eax+ebx-01] chars by 3
- :00441AA4 sub eax, 00000003
- :00441AA7 push eax <---- storing
-
- :00441AA8 lea edx, dword ptr [ebp-0C] <---- getting RegCode entry
- :00441AAB mov eax, dword ptr [esi+000002D0]
- :00441AB1 call 004231A4
-
- :00441AB6 mov eax, dword ptr [ebp-0C] <---- again getting 1 char
- :00441AB9 movzx eax, byte ptr [eax+ebx-01]
- :00441ABE pop edx <---- "remembering" and
- :00441ABF sub edx, eax subtraction
- :00441AC1 add dword ptr [00443844], edx <---- storing
-
- :00441AC7 inc ebx
- :00441AC8 dec edi
- :00441AC9 jne 00441A8E
-
- As you see, nearly the same as the Serial validation. The correct
- algorithm for creation of the RegCode:
- var index:Cardinal;
- RegCode:='';
- for index:=1 to Length(User) do
- RegCode:=RegCode+Chr(Ord(User[index])-3);
-
-
-
- Code snippet $00441ACB-$00441AEB:
- ---------------------------------
- Here, 2 calls to another hoax routines are done. The difference of
- chars of RegCode and manipulated user name is checked, if not equal 0,
- the routine terminates.
-
- :00441ACB call 00441870 <---- hoax routine
- :00441AD0 call 0044175C <---- another hoax
- :00441AD5 mov eax, dword ptr [00443844] <---- getting the difference
- computed above
- :00441ADA add eax, 00027009 <---- just to confuse newbies
- :00441ADF cmp eax, 00027009 <---- if EAX was 0, now EAX
- must be $27009, thus the
- RegCode is recognized as
- valid.
- :00441AE4 je 00441AED <---- if OK, then proceed
- :00441AE6 call 004417E4 <---- elseway terminate
- :00441AEB jmp 00441AF5
-
-
-
- That's all, folks! Now it's up to you to write a working keygen. Or if
- you are as lazy as me, myself and I, you may play with my keygen.
- -----------------------------------------------------------------------
-
- I hope you have learned a little bit from this. Look out for my cracks:
- tutorials or source codes are included in most cases!
-
- Sincerely yours,
- The AntiXryst [CrossOver]
-
- Visit the newcoming cracking group I am the CoLeader of:
- http://crossover.tsx.org